﻿%namespace ConceptsParser.Scanner

%using ConceptsParser.Parser;
%using ConceptsParser.ParserTools;
%using QUT.Gppg;

/* ******************************** Регулярные выражения ********************************* */

Digit 		[0-9]                               // Цифра
Alpha 		[a-zA-Z_]                           // Буква (латинская для идентификатора)
AlphaDigit 	{Alpha}|{Digit}                     // Бква или цифра
EndLine 	\n									// Конец строки
ID 			{Alpha}{AlphaDigit}*                // Идентификатор


%x COMMENT_S								    // Состояние для однострочных комментариев

%%

/* ************************************** Лексемы **************************************** */

// ===================== Лексемы языка

{ID}  { 
  int res = ScannerHelper.GetIDToken(yytext);
  if (res == (int)Tokens.ID)
	yylval.sVal = yytext;
  return res;
}

"//" { 										// Однострочные комментарии
	BEGIN(COMMENT_S);	
}					
<COMMENT_S> {EndLine} { 
	BEGIN(INITIAL);
}

// ===================== Разделители

"{"  { return (int)Tokens.LBRACE; }
"}"  { return (int)Tokens.RBRACE; }
"["  { return (int)Tokens.LBRACKET; }
"]"  { return (int)Tokens.RBRACKET; }
"<"  { return (int)Tokens.LANGLE; }
">"  { return (int)Tokens.RANGLE; }
"="  { return (int)Tokens.ASSIGN; }
"==" { return (int)Tokens.EQUAL; }
"<:" { return (int)Tokens.SUBTYPE; }
">:" { return (int)Tokens.SUPERTYPE; }
";"  { return (int)Tokens.SEMICOLON; }
"."  { return (int)Tokens.POINT; }
","  { return (int)Tokens.COMMA; }


// ===================== Код в сканнер

%{
  yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
%}


%%

/* ********************************** Сопровождающий код ********************************* */

/// Вспомогательные инструменты парсера
public ParserToolsManager ToolsManager = new ParserToolsManager();

public override void yyerror(string format, params object[] args) 
{
    ToolsManager.AddSyntaxError(new SyntaxError(format, args, yylloc));
}

/// Вспомогательный класс для сканера
class ScannerHelper 
{
    /// Ключевые слова
    private static Dictionary<string,int> keywords;

    static ScannerHelper() 
    {
        keywords = new Dictionary<string,int>();
        keywords.Add("concept",(int)Tokens.CONCEPT);
        keywords.Add("explicit",(int)Tokens.EXPLICIT);
        keywords.Add("refines",(int)Tokens.REFINES);
        keywords.Add("require",(int)Tokens.REQUIRE);
        keywords.Add("type",(int)Tokens.TYPE);
        keywords.Add("using",(int)Tokens.USING);
    }
  
    /// <summary>
    /// Возвращает клиючевое слово, соответствующее строке, 
    /// или токен идентификатора
    /// </summary>
    public static int GetIDToken(string s)
    {
        if (keywords.ContainsKey(s))
            return keywords[s];
        else
            return (int)Tokens.ID;
    }
  
}
